# 1 函数
# 定义
# def 函数名():
#     函数体
# 调用
# 函数名()


def my_sum(a,b):
    return a + b
print(my_sum(1,2)) # 3


def my_cal(a,b):
    return a+b,a-b


res = my_cal(3,4)
print(res,type(res)) #(7, -1) <class 'tuple'>




# 2. 函数参数
## 2.1 必备参数 -> 写了几个就要传几个

## 2.2 默认参数 -> 所有的位置参数必须出现在默认参数前,包括函数定义和调用
def print_info(name="name",age=0):
    print(f"name:{name},age:{age}")

print_info() #name:name,age:0
print_info("zhangsan",12) #name:zhangsan,age:12




## 2.3.  可变参数 -> 参数的数量是可以改变的,可以传入多个,也可以不传
def func(*args):
    print(args,type(args),len(args))

func(1,2,3,4,5)#  (1, 2, 3, 4, 5) <class 'tuple'> 5
func() # () <class 'tuple'> 0


##  2.4. 关键字参数
def func(**kwargs):
    print(kwargs,type(kwargs),len(kwargs))

func(name="wcb",age=18) # {'name': 'wcb', 'age': 18} <class 'dict'> 2



# 3. 函数嵌套
## 3.1 嵌套调用
def f1():
    print("f1")
def f2():
    f1()
    print("f2")
f2()
# f1
# f2



def study():
    print("学习")
    def course():
        print("py")
    course()
study()
# 学习
# py


# 4. 作用域
## 4.1 全局变量 -> 在整个文件都是有效的
a = 100
def f1():
    print(f"f1中a的值{a}")
def f2():
    a = 120
    print(f"f2中a的值{a}")

f1()
f2()
print(f"执行后a的值{a}")
# f1中a的值100
# f2中a的值120
# 执行后a的值100
# a的值没有被覆盖,是因为函数内部如果要使用变量,会先从函数内部找,有的话直接使用.没有会到函数外部找


## 4.2 局部变量
def f1():
    b = 10
    print(f"a={b}") # a=10
f1()
# print(f"b={b}") # 报错


## global
a = 100
def f1():
    print(f"f1中a的值{a}")
def f2():
    global a
    a = 120
    print(f"f2中a的值{a}")

f1()
f2()
print(f"执行后a的值{a}")
# f1中a的值100
# f2中a的值120
# 执行后a的值12

def study():
    global name
    name = 'zs'
    print(f"im{name} -- in")
study()
print(f"im{name} -- out")
# imzs -- in
# imzs -- out


## nonlocal 用来声明外层的局部变量,只能在嵌套函数中使用,在外部函数先进行声明,内部函数进行nonlocal声明
a = 10
def outer():
    a = 5
    def inner():
        nonlocal a
        a = 20
        print("inner: a=",a)
    inner()
    print("outer: a=",a)

outer()
# inner: a= 20
# outer: a= 20